home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 August: Tool Chest / Dev.CD Aug 98 TC.toast / Tool Chest / Testing & Debugging / Mac OS Development Toolkit / Automation Essentials 2.3.0 / Host Automation Folder / Clouseau libs / Message.lib < prev    next >
Encoding:
Text File  |  1998-03-19  |  13.2 KB  |  297 lines  |  [TEXT/MPS ]

  1. #########################################################################
  2. #########################################################################
  3. ##                     Copyright © Apple Computer, Inc. 1992-1997
  4. ##                                All rights reserved
  5. #########################################################################
  6. #########################################################################
  7. #    
  8. #    Library:        Message.lib
  9. #    
  10. #    Version:        2.1.4
  11. #    
  12. #    Description:    
  13. #        Contains helpful tasks for actors to communicate between themselves 
  14. #        using the VU message passing mechanism. They are essentially the four 
  15. #        messaging primitives with some error checking and reporting added on. 
  16. #        For a complete description of the messaging feature, see the Virtual 
  17. #        User Language Reference. Here are some tips:
  18. #        
  19. #        Actors do not exist unless they are running a script. The statement:
  20. #            match[actor t:$allActors];
  21. #        puts a list of actors into allActors, but only those which are 
  22. #        currently running scripts (the scripts can be the same or different).
  23. #        For messaging, the term "actor" refers to an actor running a script.
  24. #        
  25. #        A message consists of a string. As long as you have opened a session 
  26. #        with another actor, you can send a list of messages, which is relatively
  27. #        fast to complete from your actor's point of view, because the whole list 
  28. #        is accepted as one parameter by the send() primitive. However, receiving 
  29. #        a list is slow, since the receive() primitive returns just one message at 
  30. #        a time, even if the sender sent a list. You must loop until you receive all 
  31. #        expected messages, which implies you must know in advance how many were sent.
  32. #        
  33. #        Actors must agree in advance (by design is easier than by negotiation) on
  34. #        the kinds of messages possible and their length. This way the first
  35. #        message received tells what kind of message, and by its definition implies 
  36. #        how many more will follow, so you know when to terminate the loop.
  37. #        One of the most common causes of failure when using messages is getting
  38. #        de-synchronized, where one actor is re-sending after the other's 
  39. #        response has been sent, but has not yet reached the first actor.
  40. #        
  41. #        Message strings take several seconds each (at least) to get to the 
  42. #        other actor. This is an artifact of their implementation. Currently
  43. #        there are no plans to improve the performance of messages, so you
  44. #        should not use them extensively. Their main use in the LaunchQuit 
  45. #        engine is to allow registration of applications which perform 
  46. #        serial number conflict checking over the network, so that if one
  47. #        actor has launched the application, others are locked out until the
  48. #        current actor un-registers. This is rare enough that the substantial 
  49. #        additional time to complete the test case (more than a minute if no other 
  50. #        applications have registered first) does not substantially alter the 
  51. #        average time per test case. See the script called Arbitrator.vu.
  52. #        
  53. #        Messaging can take a really long time if all actors send and receive
  54. #        to and from the same actor (e.g. the Arbitrator) which must service each 
  55. #        actor in round-robin fashion. You will need to use large timeout 
  56. #        values to prevent unexpected failures when receiving. Again, sending takes
  57. #        little time because it does not wait for a response from the other actor.
  58. #        It is almost as if messages are "posted" on a bulletin board, then each
  59. #        actor looks at the board everytime its thread becomes active, and grabs
  60. #        any messages for itself. The posting takes almost no time, but since only 
  61. #        one message is received for each thread switch, receiving takes longer.
  62. #    
  63. #    Contains:
  64. #        connect_to()
  65. #        disconnect_from()
  66. #        send_list()
  67. #        receive_list()
  68. #    
  69. #    History:
  70. #        Date:        By:        Changes:
  71. #        12/15/92    SBR        Created
  72. #        02/01/94    SBR        Added comments
  73. #        06/01/96    SBR/MSO    Updated copyright header
  74. #        01/21/97    SBR        Updated copyright header.
  75. #    
  76. #########################################################################
  77. #########################################################################
  78. Libraries
  79.     "Clouseau.lib", 
  80.     "Report.lib";
  81.  
  82.  
  83. #########################################################################
  84. #    task            connect_to( toWhom, maxTime, v_level )
  85. #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
  86. #    Description:    Use this to open a session with another actor. Once the other actor
  87. #                    calls connect_to() with your actor's name, then both can send messages 
  88. #                    to each other.
  89. #    Parameters:        toWhom:        string name of the running actor to open a session with
  90. #                    maxTime:    integer maximum number of seconds to wait for the other  
  91. #                                actor to open a session with your actor; make this fairly
  92. #                                large if multiple actors are running
  93. #                    v_level:    verbosity level for debugging
  94. #    Returns:        true:    The session opened within the allotted time.
  95. #                    false:    The session did not open within the allotted time. This 
  96. #                            Note:    The session may still open later since the other actor   
  97. #                                    may keep trying. However, never try messaging unless 
  98. #                                    this routine returns true.
  99. #    Examples:        if not connect_to('Arbitrator',60)
  100. #                        println "Could not connect to the Arbitrator, is it running?";
  101. #    Assumptions:    None
  102. #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
  103. #        History:
  104. #            12/15/92    SBR        Created
  105. #            02/01/94    SBR        Added ! to make the actor match exact
  106. #            02/02/94    SBR        Changed timer to use real time
  107. #            08/06/94    SBR        Changed timer to use timed_out, removed RIncomplete v_level
  108. #########################################################################
  109. task connect_to( toWhom := '', maxTime := 10, v_level := 3 )
  110. begin
  111.     RStatus("connect_to: Open session with '{toWhom}' within {maxTime} seconds", v_level);
  112.  
  113.     end_time := get_end_time(maxTime);
  114.     status := '';
  115.     outOfTime := false;
  116.  
  117.     while (status <> 'open') and (not outOfTime)        #always try once
  118.     begin
  119.         if not match[actor t:toWhom]!
  120.             return RIncomplete("connect_to: The actor '{toWhom}' is not present");
  121.         status := openSession([actor t:toWhom]);
  122.         
  123.         theError := ScriptError();
  124.         if theError
  125.             return RIncomplete("connect_to: connect to '{toWhom}' failed " +
  126.                                 "(status: {status}, ScriptError: {theError}).");
  127.             
  128.         RStatus("connect_to: Status is {status} after this attempt.", v_level);
  129.         wait(1);
  130.         
  131.         outOfTime := timed_out(end_time);
  132.     end;
  133.     if status = 'open'
  134.         return RStatus("connect_to: connect to '{toWhom}' succeeded.", v_level);
  135.     else 
  136.         return RIncomplete("connect_to: connect to '{toWhom}' failed ({status}).");
  137. end;
  138.  
  139. #########################################################################
  140. #    task            disconnect_from( fromWhom, v_level )
  141. #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
  142. #    Description:    Use this to close a session with another actor which was already open.
  143. #                    Note:     This does not require the other actor to respond or even to 
  144. #                            disconnect, so there is no timeout value. The only way it can 
  145. #                            fail is if the session is not open at this end. It may already
  146. #                            be closed at the other end.
  147. #    Parameters:        fromWhom:    string name of the connected actor to disconnect from
  148. #                    v_level:    verbosity level for debugging
  149. #    Returns:        true:    The session was open and now is closed.
  150. #                    false:    The session was not open at this end, but it is closed now.
  151. #    Examples:        if not disconnect_from('Arbitrator')
  152. #                        println "Could not disconnect to the Arbitrator, was it connected?";
  153. #    Assumptions:    Already connected at other end.
  154. #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
  155. #        History:
  156. #            12/15/92    SBR        Created
  157. #            02/01/94    SBR        Added ! to make the actor match exact
  158. #            08/06/94    SBR        Added ScriptError() check, removed RIncomplete v_level
  159. #########################################################################
  160. task disconnect_from( fromWhom := '', v_level := 3 )
  161. begin
  162.     RStatus("disconnect_from: Attempting to close session with '{fromWhom}'",v_level);
  163.  
  164.     wait(1);
  165.  
  166.     if not match [actor t:fromWhom]!
  167.         return RIncomplete("disconnect_from: The actor '{fromWhom}' is not present");
  168.     status := closeSession([actor t:fromWhom]);
  169.  
  170.     theError := ScriptError();
  171.     if theError
  172.         return RIncomplete("disconnect_from: disconnect from '{fromWhom}' failed " +
  173.                             "(status: {status}, ScriptError: {theError}).");
  174.  
  175.     if status = 'done'
  176.         return RStatus("disconnect_from: disconnect from '{fromWhom}' succeeded.", v_level);
  177.     else 
  178.         return RIncomplete("disconnect_from: disconnect from '{fromWhom}' failed " +
  179.                             "(status: {status}).");
  180. end;
  181.  
  182.  
  183. #########################################################################
  184. #    task            send_list( toWhom, myList := {}, v_level )
  185. #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
  186. #    Description:    Use this to send messages to another actor you have already opened
  187. #                    a session with that actor using connect_to(). The other actor must 
  188. #                    know how many items you are sending.
  189. #                    Note:    Generally, the only way for this to fail is if the session
  190. #                            is not already open or if the actor is no longer running a 
  191. #                            script. The real work goes on at the receiver.
  192. #    Parameters:        toWhom:        string name of the connected actor you want to send to
  193. #                    myList:        list of regular expressions or integers, which VU  
  194. #                                converts to a list of strings before sending.
  195. #                    v_level:    verbosity level for debugging
  196. #    Returns:        true:    The messages were sent with no errors.
  197. #                    false:    There was an error sending the messages.
  198. #    Examples:        if not send_list('Arbitrator', {'useApplication','Canvas 3.0.6@'})
  199. #                        println "Could not send to the Arbitrator, is it still running?";
  200. #    Assumptions:    Session is already open with other actor
  201. #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
  202. #    History:
  203. #        12/15/92    SBR        Created
  204. #        08/06/94    SBR        Removed RIncomplete v_level
  205. #########################################################################
  206. task send_list( toWhom := '', myList := {}, v_level := 3 )
  207. begin
  208.     listLength := card myList;
  209.     sendSuccess := send([actor t:toWhom], myList);
  210.  
  211.     theError := ScriptError();
  212.     if theError 
  213.         RIncomplete("send_list: Error {theError} sending '{toWhom}' " +
  214.                     "the message:{myList} (status: {sendSuccess}, ScriptError: {theError}).");
  215.     if sendSuccess
  216.         return RStatus("send_list: Sent '{toWhom}' a message with {listLength} items.", v_level);
  217.     else 
  218.         return RIncomplete("send_list: Failed to send '{toWhom}' the message:{myList}.");
  219. end;
  220.  
  221.  
  222. #########################################################################
  223. #    task            receive_list( fromWhom, msgNum, maxTime, v_level )
  224. #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
  225. #    Description:    Use this to receive messages from another actor. The receive()
  226. #                    primitive may return a null string in between consecutive messages 
  227. #                    sent from another actor, even if they were sent in the same list. 
  228. #                    For this reason, this task loops over a specified period of time,
  229. #                    until the expected number of non-null strings are returned. This
  230. #                    means you can not send a null string on purpose.
  231. #    Parameters:        fromWhom:    string: name of the connected actor to receive from
  232. #                    msgNum:        integer: expected number of messages to receive within the
  233. #                                amount of time allowed
  234. #                    maxTime:    integer: maximum total number of seconds to  
  235. #                                receive ALL the messages (not each message); make this 
  236. #                                fairly large if multiple actors are running
  237. #                    v_level:    integer: verbosity level for debugging
  238. #    Returns:        true:    Within maxTime seconds, msgNum strings were received with
  239. #                            no errors.
  240. #                    false:    There was an error, or msgNum messages were not received
  241. #                            within maxTime seconds.
  242. #    Examples:        myReceivedMsgs := receive_list('Arbitrator',3,180);
  243. #                    if not myReceivedMsgs
  244. #                        println "Could not receive 3 messages from the Arbitrator!";
  245. #    Assumptions:    Session is already open with other actor. It is not required that 
  246. #                    the other actor sends anything, but the caller of this routine
  247. #                    must decide when to give up.
  248. #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
  249. #    History:
  250. #        12/15/92    SBR        Created
  251. #        02/02/94    SBR        Added return for ScriptError case, changed timer to "manual"
  252. #        08/06/94    SBR        Changed timer to use timed_out, removed RIncomplete v_level
  253. #########################################################################
  254. task receive_list( fromWhom := '', msgNum := 1, maxTime := 10, v_level := 3 )
  255. begin
  256.     msgsRcd := {};
  257.     rTries := 0;
  258.     allDone := false;
  259.     outOfTime := false;
  260.     end_time := get_end_time(maxTime);
  261.     
  262.     while not (outOfTime or allDone)            #always try once
  263.     begin
  264.         rTries := rTries + 1;
  265.         msgReceived := receive([actor t:fromWhom]);
  266.         
  267.         theError := ScriptError();
  268.         if theError
  269.         begin
  270.             returnString := "receive_list: Error {theError} receiving {msgNum}" + 
  271.                             " items from '{fromWhom}' at item #{rTries}'." + 
  272.                             " Partial msg: {msgsRcd}.";
  273.             return RIncomplete(returnString);
  274.         end;
  275.  
  276.         if msgReceived 
  277.         begin
  278.             RStatus("receive_list: Received message '{msgReceived}' on attempt #{rTries}.", v_level);
  279.             msgsRcd := msgsRcd + {msgReceived};
  280.             if card msgsRcd = msgNum
  281.                 return msgsRcd;
  282.         end;
  283.         else 
  284.             RStatus("receive_list: Received nothing from '{fromWhom}' on attempt #{rTries}.", v_level);
  285.             
  286.         if timed_out(end_time) 
  287.         begin
  288.             outOfTime := true;
  289.             returnString := "receive_list: Timed out receiving from '{fromWhom}'";
  290.             return RIncomplete("{returnString}, attempt #{rTries}. Partial msg: {msgsRcd}.");
  291.         end;
  292.         wait(1);
  293.     end;
  294. end;
  295.  
  296.  
  297.